/**
 * @author haina.z@163.com
 * @brief header file, 铁标协议通讯框架.
 * @version V1.0
 */

#ifndef __COM_RR_DLL_H
#define __COM_RR_DLL_H

/** Includes -----------------------------------------------------------------*/
#include "public_defs.h"
#include "prj_config.h"

/** C++ { --------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif

/** Macros (#define) ---------------------------------------------------------*/
// 缓冲区大小
#ifndef COM_RR_BUF_SIZE
#define COM_RR_BUF_SIZE                                     100         // 内存大小
#endif

/** Type definitions ---------------------------------------------------------*/
typedef struct
{
    uint8_t u8Head;
    uint8_t u8CrcH;
    uint8_t u8CrcL;
    uint8_t u8Tail;
} COM_RR_DLL_t;

// 通讯控制
typedef struct
{
    uint8_t             state;                      // 状态
    struct
    {
        uint8_t         timer;                      // 超时计数
        uint8_t         step;                       // 接收控制

        uint8_t *       MemPtr;                     // 内存指针
        uint16_t        FactCnt;                    // 接收加计数
        uint8_t         buf[COM_RR_BUF_SIZE];       // 缓冲区

        uint8_t         Valid;                      // 接收有效
        uint16_t        Len;                        // 接收长度
    } recv;                                         // 接收
    struct
    {
        uint8_t         timer;                      // 超时计数

        uint8_t *       MemPtr;                     // 内存指针
        uint16_t        FactCnt;                    // 发送减计数
        uint8_t         buf[COM_RR_BUF_SIZE];       // 缓冲区

        uint8_t         spacetime;                  // 帧间间隔
    } send;                                         // 发送
} COM_RR_INST;

/** External variable declarations (extern) ----------------------------------*/

/** Function declarations (prototypes) ---------------------------------------*/
uint16_t ComRRDll_CalculateCRC(uint8_t * ptr, uint16_t len);
void ComRRDll_TimeUpdate(COM_RR_INST * pCurCom);
void ComRRDll_RecvEvent(COM_RR_INST * pCurCom, uint8_t dat);
uint8_t ComRRDll_StartSend(COM_RR_INST * pCurCom, uint8_t * Buf, uint16_t Len, uint8_t * pdat);
uint8_t ComRRDll_SendEvent(COM_RR_INST * pCurCom, uint8_t * pdat);
uint16_t ComRRDll_BuildSendFrame(COM_RR_INST * pCurCom, uint16_t DatLen);

/** Macros (#define) ---------------------------------------------------------*/
// 接收
#define mComRRDll_RecvIsCompleted(pCom)                     ((pCom)->recv.Valid > 0)
#define mComRRDll_ClrRecvComplete(pCom)                     do { (pCom)->recv.Valid = 0; } while(0)

#define mComRRDll_GetRecvBuffer(pCom)                       ((pCom)->recv.MemPtr)
#define mComRRDll_GetRecvLength(pCom)                       ((pCom)->recv.Len)
#define mComRRDll_CheckRecvFrameWithBufLen(buf, len)        (((len) > sizeof(COM_RR_DLL_t)) \
&& (ComRRDll_CalculateCRC(&((buf)[1]), ((len) - sizeof(COM_RR_DLL_t))) == (((uint16_t)((buf)[(len) - 3]) << 8) + (buf)[(len) - 2])))

#define mComRRDll_CheckRecvFrame(pCom)                      mComRRDll_CheckRecvFrameWithBufLen(mComRRDll_GetRecvBuffer(pCom), mComRRDll_GetRecvLength(pCom))

#define mComRRDll_GetRecvDatPtr(pCom)                       (&((pCom)->recv.MemPtr[1]))
#define mComRRDll_GetRecvDatLen(pCom)                       ((pCom)->recv.Len - sizeof(COM_RR_DLL_t))

// 发送
#define mComRRDll_CanSend(pCom)                             (((pCom)->send.FactCnt == 0) && ((pCom)->send.spacetime == 0))
#define mComRRDll_GetSendDatPtr(pCom)                       (&((pCom)->send.buf[1]))
#define mComRRDll_StartSend(pCom, len, pDat)                ComRRDll_StartSend((pCom), (pCom)->send.buf, (len), (pDat))

/** C++ } --------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif

#endif // COM_RR_DLL
/******************************** End of file *********************************/
